/**
* \brief Sorts strings in the text
*
* This function gets strings from file "onegin.txt", sorts it and the puts sorted strings
* in the file "onegin_sorted.txt"
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "../Debug/main.c"
#include "main.h"
typedef int comp_func (const void *, const void *);

int main()
{
    FILE* original_poem = fopen("onegin.txt", "r");
    long poem_lenght = get_file_length(original_poem);
    DEBUG_OPEN();
    char* buffer = fread_to_string(original_poem, poem_lenght);
    long nmb_of_strs = get_string_number(buffer);
    char** poem_strings = get_strings(buffer, nmb_of_strs);
    qsort(poem_strings, nmb_of_strs, sizeof(*poem_strings), (comp_func*)STRCMP);
    FILE* output_file = fopen("sorted_onegin.txt", "w");
    for (long i = 0; i < nmb_of_strs; i++)
    {
        fprintf(output_file,"%s\n",poem_strings[i]);
    }


    for (long i = 0; i < nmb_of_strs; i++)
    {
        poem_strings[i] = NULL;
    }
    free(poem_strings);
    poem_strings = NULL;
    free(buffer);
    buffer = NULL;
    fclose(original_poem);
    original_poem = NULL;
    DEBUG_CLOSE();
    return 0;
}

/**
* \brief This fucntion returns file length
*
* This fucntion count file length and returns it then.
* @param file File that will be read
* @return file_length Length of read file
*/
long get_file_length(FILE* file)
{
    fseek(file, 0, SEEK_END);
    long file_length = ftell(file)+1;
    fseek(file, 0, SEEK_SET);
    return file_length;
}

/**
* \brief This function reads all content from file, creates the string and copyes content from file to string.
*
* This function reads all content from file, creates the string and copyes content from file to string.
* You can read many-string files so, string will contain symbols '\n' and maybe '\r'
*
* @param file File content will be read from
* @param file_length Length of file
* @return buffer Created string
*/
char* fread_to_string(FILE* file, long file_length)
{
    char* buffer = (char*)calloc(file_length, sizeof(*buffer));
    assert(buffer);
    fread (buffer, sizeof(*buffer), file_length, file);
    return buffer;
}

/**
* \brief This functuon counts number of strings in array of symbols
*
* This functuon counts number of strings in array of symbols
* @param text Scanned array of symbols(must be ended by '\0')
* @return nmb_of_strs Counted number of strings
*/
long get_string_number(char* text)
{
    long nmb_of_strs = 0;
    while (*text != '\0')
    {
        if (*text == '\n')
        {
            nmb_of_strs++;
            if (*text == '\r')
            {
                text++;
            }
        }
        text++;
    }
    text--;
    text--; //Need to know if there was last '\n'
    if (*text != '\n')
    {
        nmb_of_strs++;
    }
    return nmb_of_strs;
}

/**
* \brief This function splits array of symbols in separated strings
*
* This function splits array of symbols in separated strings
* @param text Text from which fuction will get the strings
* @param nmb_of_strs Number of strings you want to get
* @see get_string_number
*/
char** get_strings(char* text, long nmb_of_strs)
{
    char** poem_strings = (char**)calloc (nmb_of_strs, sizeof(*poem_strings));
    assert(poem_strings);
    poem_strings[0] = text;
    for (long i = 1; i < nmb_of_strs; i++, text++)
    {
        while (*text != '\n')
        {
            text++;
            //Skips all the string
        }
        *text = '\0';
        poem_strings[i] = text + 1;
        if (poem_strings[i][0] == '\r')
        {
            poem_strings[i]++;
        }
    }
    return poem_strings;
}

/**
* \brief Wrapping of standart strcmp made for corretc work of qsort
*
* @param str1 First comparable string
* @param str2 Second comparable string
* @return result of standart strcmp
*/
int STRCMP (const char** str1, const char** str2)
{
    assert ( str1); assert ( str2);
    assert (*str1); assert (*str2);

    return strcmp (*str1, *str2);
}
